// 采用es5的构造函数
import {initState} from './observe'
import Watcher from './observe/watcher';
import {util, compiler} from './util'
function Vue(options) { // vue中原始用户传入的数据
  this._init(options) // 初始化vue 并且将用户选项传入
}

Vue.prototype._init = function (options) {
  // vue中初始化 this.$options 表示的事vue中参数
  let vm = this
  vm.$options = options
  //MVVM原理 需要数据重新初始化 Object.defineProperty
  initState(vm); // data computed watch

  // ...
  // 初始化工作
  if(vm.$options.el) {
    vm.$mount()
  }
}

function query (el) {
  if(typeof el === 'string') {
    return document.querySelector(el)
  }
  return el
}

Vue.prototype._update = function () {
  // 用户传入的数据 去更新视图
  let vm = this
  let el = vm.$el

  // ---------------以下逻辑 讲完虚拟dom 会用虚拟dom来重写
  // 要循环这个元素 将里边的内容 换成我们的数据
  let node = document.createDocumentFragment()
  let firstChild
  while(firstChild = el.firstChild) { // 每次拿到第一个元素就将这个元素放入到文档碎片中
    node.appendChild(firstChild) // appendChild 是具有移动的功能
  }
  // console.log(node)
  // todo 对文本进行替换
  compiler(node, vm)
  el.appendChild(node)
  // 需要匹配{{}}的方式来进行替换

  // 依赖收集  属性变化了 需要重新渲染 watcher 和 dep
}

// 渲染页面 将组建进行挂载
Vue.prototype.$mount = function() {
  let vm = this
  let el = vm.$options.el // 获取元素 // #app
  el= vm.$el = query(el) // 获取当前挂载的节点  vm.$el就是我要挂载的一个元素

  // 渲染时通过watcher来渲染
  // 渲染watcher 用于渲染的watcher
  // vue2.0 组件级别更新 new Vue 产生一个组件
  let updatedComponent = () => { // 更新组件、渲染的逻辑
    console.log('updatedComponent 执行了')
    vm._update()  //更新组件
  }

  new Watcher(vm, updatedComponent) // 渲染watcher,默认会调用updatedComponent方法


}

export default Vue